package edu.gdin.ecommerce.security.support;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.util.AntUrlPathMatcher;
import org.springframework.security.web.util.UrlMatcher;

import edu.gdin.ecommerce.dao.RoleDAO;
import edu.gdin.ecommerce.model.Func;
import edu.gdin.ecommerce.model.Role;

public class MyInvocationSecurityMetadataSource implements
		FilterInvocationSecurityMetadataSource {

	/** 日志处理器 */
	protected  Log logger = LogFactory.getLog(getClass());
	
	private UrlMatcher urlMatcher = new AntUrlPathMatcher();
	private static Map<String, Collection<ConfigAttribute>> resourceMap = null;
	
//	private UserDAO userDAO;
	private RoleDAO roleDAO;
	

//	public UserDAO getUserDAO() {
//		return userDAO;
//	}
//	@Resource
//	public void setUserDAO(UserDAO userDAO) {
//		this.userDAO = userDAO;
//	}
	public RoleDAO getRoleDAO() {
		return roleDAO;
	}
	@Resource
	public void setRoleDAO(RoleDAO roleDAO) {
		this.roleDAO = roleDAO;
	}
	
	@SuppressWarnings("unchecked")
	public MyInvocationSecurityMetadataSource(RoleDAO roleDAO) {
		this.roleDAO = roleDAO;
		List<Func> funs  = (List<Func>) roleDAO.list(Func.class);		
		List<Role> roles = (List<Role>) roleDAO.getAll();
		MyInvocationSecurityMetadataSource.loadPower(funs, roles);
	}

	public static void loadPower(List<Func> funs, List<Role> roles){
		loadResourceDefine(funs);
		loadRoleList(roles);
	}
	
	private static  void loadResourceDefine(List<Func> funcs) {
		/*
		 * 应当是资源为key， 权限为value。 资源通常为url， 权限就是那些以ROLE_为前缀的角色。
		 * 一个资源可以由多个权限来访问。
		 */
		resourceMap = new HashMap<String, Collection<ConfigAttribute>>();		
		for(Func func : funcs){
			if (!resourceMap.containsKey(func.getUrl())) {
				Collection<ConfigAttribute> cas = new ArrayList<ConfigAttribute>();
				//cas.add(new SecurityConfig("no right"));
				resourceMap.put(func.getUrl(), cas);
			}		
		}
	}
	
	private static void loadRoleList(List<Role> roles){
		for (Role role : roles) {
			loadRole(role);
		}		
	}
	
	public static void loadRole(Role role){
		ConfigAttribute ca = new SecurityConfig(role.getName());
		
		for (Func res : role.getFuncs()) {
			String url = res.getUrl();
			/*
			 * 判断资源文件和权限的对应关系，如果已经存在相关的资源url，则要通过该url为key提取出权限集合，将权限增加到权限集合中。 
			 */
			if (resourceMap.containsKey(url)) {
				Collection<ConfigAttribute> cas = resourceMap.get(url);	
				cas.add(ca);
				resourceMap.put(url, cas);
			} else {
				Collection<ConfigAttribute> cas = new ArrayList<ConfigAttribute>();
				cas.add(ca);
				resourceMap.put(url, cas);
			}
		}
	}
	

	

	// 根据URL，找到相关的权限配置。
	public Collection<ConfigAttribute> getAttributes(Object object)
			throws IllegalArgumentException {

		// object 是一个URL，被用户请求的url。
		String url = ((FilterInvocation) object).getRequestUrl();
		if(logger.isDebugEnabled()){
			logger.debug("访问URL:"+ url);
		} 

		int firstQuestionMarkIndex = url.indexOf("?");
		if (firstQuestionMarkIndex != -1) {
			url = url.substring(0, firstQuestionMarkIndex);
		}

		Iterator<String> ite = resourceMap.keySet().iterator();
		while (ite.hasNext()) {
			String resURL = ite.next();
			if (urlMatcher.pathMatchesUrl(url, resURL)) {
				return resourceMap.get(resURL);
			}
		}

		return null;
	}

	
	public boolean supports(Class<?> arg0) {

		return true;
	}
	
	public Collection<ConfigAttribute> getAllConfigAttributes() {

		return null;
	}

}
